<!-- 上传 -->
<template>
	<view class="vk-data-upload" :class="quickPreview ? 'quick-preview' : ''">
		<!-- 页面开始 -->
		<view v-if="quickPreview">
			<image
				v-if="lists && lists.length"
				:src="lists[previewIndex].url"
				:style="'width: '+widthCom+';height: ' + heightCom + ';display: block;'"
				:mode="imageMode"
				@click="previewImage(lists[previewIndex].url)"
			></image>
			<view
				v-else
				class="chooseImage-view"
				:style="{
					width: widthCom,
					height: heightCom
				}"
				@click="chooseImage"
			>
				<view><image :src="defaultImage" class="default-image"></image></view>
				<view>{{ placeholder }}</view>
				<view class="upload-btn">{{ uploadText }}</view>
			</view>
		</view>
		
		<view class="header-view" v-if="showHeader">
			<view v-if="title" class="left-view">{{ title }}</view>
			<view v-if="limit > 1" class="right-view">{{ limitTitleCom }}</view>
		</view>
		
		<view style="padding: 10rpx;" v-if="(quickPreview && lists && lists.length) || !quickPreview">
			<view class="lists-view">
				<view v-for="(item, index) in lists" :key="index" class="image-item-view" style="">
					<image :src="item.url" class="image-item" @click="imageItemClick(item.url, index)"></image>
					<view class="image-mask" v-if="item.error">
						<view class="progress" @click="uploadFile">重试</view>
					</view>
					<view class="image-mask" v-else-if="item.progress < 100">
						<view class="progress">{{ item.progress }}%</view>
					</view>
					<view class="image-mask" v-else-if="quickPreview && previewIndex == index"></view>
					<view v-if="!disabled" class="delete-btn" @click="deleteImage(index)">×</view>
				</view>
				<view
					v-if="lists.length < limit"
					class="image-item-view upload-btn-sub"
					@click="chooseImage"
				>
					<view class="item-1"></view>
					<view class="item-2"></view>
				</view>
			</view>
		</view>
		<!-- 页面结束 -->
	</view>
</template>

<script>
export default {
	name: "vk-data-upload",
	emits: ["update:modelValue", "input", "on-progress", "on-success", "on-error","on-preview"],
	props: {
		// 表单值
		value: {},
		modelValue: {},
		// 提示
		placeholder: {
			Type: String
		},
		defaultImage: {
			type: String,
			default:
				""
		},
		width: {
			type: [String, Number],
			default: 200
		},
		height: {
			type: [String, Number]
		},
		// 是否显示快速预览
		quickPreview: {
			type: Boolean,
			default: false
		},
		// 图片显示模式
		imageMode: {
			type: String,
			default: "aspectFill"
		},
		// 是否禁用
		disabled: {
			type: Boolean,
			default: false
		},
		// 是否在点击预览图后展示全屏图片预览
		previewFullImage: {
			type: Boolean,
			default: true
		},
		
		showHeader: {
			type: Boolean,
			default: false
		},
		needSave: {
			type: Boolean,
			default: false
		},
		title: {
			type: String,
			default: "上传图片"
		},
		// 最大上传数量
		limit: {
			type: Number,
			default: 99
		},
		// 服务供应商
		provider: {
			type: String
		},
		// 选择图片按钮的提示文字
		uploadText: {
			type: String,
			default: "选择图片"
		},
		// 所选的图片的尺寸, 可选值为original compressed
		sizeType: {
			type: Array,
			default() {
				return ["original", "compressed"];
			}
		},
		// 所选的图片的来源
		sourceType: {
			type: Array,
			default() {
				return ["album", "camera"];
			}
		},
		
		maxSize: {
			type: [String, Number],
			default: 999999999
		}
	},
	data: function() {
		// 组件创建时,进行数据初始化
		return {
			// 预览图
			previewIndex: 0,
			lists: []
		};
	},
	mounted() {
		this.init();
	},
	methods: {
		// 初始化
		init() {
			let that = this;
			let { valueCom: value, vk, limit } = that;
			if (vk.pubfn.isNull(value) && limit > 1) {
				that._updateValue([]);
			}
		},
		// 向父组件发送更新value事件
		_updateValue(value) {
			let that = this;
			let { limit } = that;
			if (limit == 1) {
				if (typeof value === "object") {
					value = value[0];
				}
			}
			that.$emit("input", value);
			that.$emit("update:modelValue", value);
		},
		// 选择图片
		chooseImage() {
			let that = this;
			let { sizeType, sourceType, lists, limit, maxSize, disabled } = that;
			if (lists.length >= limit) {
				return false;
			}
			if (disabled) {
				return false;
			}
			uni.chooseImage({
				count: limit, //默认9
				sizeType, //可以指定是原图还是压缩图，默认二者都有
				sourceType, //从相册选择
				success: function(res) {
					res.tempFiles.map((val, index) => {
						if (val.size > maxSize) {
							that.$emit("on-oversize", val, that.lists, that.index);
							uni.showToast({
								title: "超出允许的文件大小",
								icon: "none"
							});
						}
						if (lists.length >= limit) {
							that.$emit("on-exceed", val, that.lists, that.index);
							uni.showToast({
								title: "超出最大允许的文件个数",
								icon: "none"
							});
							return;
						}
						lists.push({
							url: val.path,
							progress: 0,
							error: false,
							file: val
						});
					});
					that.lists = JSON.parse(JSON.stringify(lists));
					that.uploadFile();
				}
			});
		},
		// 删除图片
		deleteImage(index) {
			let that = this;
			let { previewIndex = 0, vk, valueCom: value, limit } = that;
			vk.confirm("确定删除吗？","删除提示","确定","取消",function(res){
				if(res.confirm){
					if (vk.pubfn.isNull(value)) {
						that.lists.splice(index,1);
					}
					if (previewIndex >= that.lists.length - 1) {
						that.previewIndex = 0;
					}
					if (limit > 1) {
						value.splice(index, 1);
					} else {
						value = "";
					}
					that._updateValue(value);
				}
			});
		},
		// 监听内部文件变化 - 实现自定义上传
		async uploadFile() {
			let that = this;
			let { provider, vk, lists:list } = that;
			if (!provider) {
				let config = vk.callFunctionUtil.getConfig();
				let aliyunOSS = vk.pubfn.getData(config, "service.aliyunOSS");
				if (aliyunOSS && aliyunOSS.isDefault) {
					provider = "aliyun";
				} else {
					provider = "unicloud";
				}
			}
			let tasks = [];
			list.map((item, index) => {
				if (item.progress < 100) {
					if (provider === "unicloud") {
						tasks.push(that.beforeUpload_unicloud(index, list));
					} else if (provider === "aliyun") {
						tasks.push(that.beforeUpload_aliyunoss(index, list));
					}
				}
			});
			await Promise.all(tasks);
			let images = [];
			that.lists.map((item, index) => {
				images.push(item.url);
			});
			that._updateValue(images);
		},
		// 上传到unicloud
		beforeUpload_unicloud(index, list) {
			let that = this;
			let { vk, limit, needSave } = that;
			let tempFilePath = list[index].url;
			let file = list[index].file;
			return vk.callFunctionUtil.uploadFile({
				filePath: tempFilePath,
				fileType: "image",
				provider: "unicloud",
				file,
				needSave,
				onUploadProgress: function(res) {
					if (res.progress > 0) {
						if (list[index]) {
							list[index].progress = res.progress;
							that.$emit("on-progress", res, index, list);
						}
					}
				},
				success: function(res) {
					// 上传成功
					let url = res.fileID;
					list[index].response = "ok";
					list[index].progress = 100;
					list[index].error = false;
					list[index].url = url;
					that.$emit("on-success", res, index, list);
					let images = that.valueCom;
					if (limit > 1) {
						if (!images || images.length == 0) {
							images = [];
						}
						images.push(url);
					} else {
						images = url;
					}
					//that._updateValue(images);
				},
				fail: function(res) {
					// 上传失败
					list[index].error = true;
					that.$emit("on-error", res, index, list);
				}
			});
		},
		// 上传到阿里云oss
		beforeUpload_aliyunoss(index, list) {
			let that = this;
			let { limit, vk, needSave } = that;
			let tempFilePath = list[index].url;
			let file = list[index].file;
			return vk.callFunctionUtil.uploadFile({
				filePath: tempFilePath,
				fileType: "image",
				provider: "aliyun",
				index,
				file,
				needSave,
				onUploadProgress: function(res) {
					if (res.progress > 0) {
						if (list[index]) {
							list[index].progress = res.progress;
							that.$emit("on-progress", res, index, list);
						}
					}
				},
				success: function(res) {
					// 上传成功
					let url = res.fileID;
					list[index].response = res;
					list[index].progress = 100;
					list[index].error = false;
					that.$emit("on-success", res, index, list);
					let images = that.valueCom;
					if (limit > 1) {
						if (!images || images.length == 0) {
							images = [];
						}
						images.push(url);
					} else {
						images = url;
					}
					that._updateValue(images);
				},
				fail: function(res) {
					// 上传失败
					that.$emit("on-error", res, index, list);
				}
			});
		},
		// 图片预览
		previewImage(url, index){
			let that = this;
			let { previewIndex, lists, previewFullImage } = that;
			if (index == undefined) index = previewIndex;
			if (!previewFullImage){
				that.$emit('on-preview', url, lists, index);
				return;
			} 
			const images = lists.map(item => item.url || item.path);
			uni.previewImage({
				urls: images,
				current: url,
				success: () => {
					that.$emit('on-preview', url, lists, index);
				},
				fail: () => {
					uni.showToast({
						title: '预览图片失败',
						icon: 'none'
					});
				}
			});
		},
		// 图片item点击
		imageItemClick(url, index){
			let that = this;
			let { quickPreview, previewFullImage } = that;
			that.previewIndex = index;
			if (!quickPreview && previewFullImage) {
				that.previewImage(url, index);
			}
		}
	},
	// 监听器
	watch: {
		valueCom: {
			immediate: true,
			handler: function(newVal, oldVal) {
				let that = this;
				let lists = [];
				if (newVal) {
					if (that.limit == 1) {
						lists.push({
							url: newVal,
							progress: 100,
							error: false
						});
					} else {
						newVal.map((item, index) => {
							lists.push({
								url: item,
								progress: 100,
								error: false
							});
						});
					}
				}
				that.lists = JSON.parse(JSON.stringify(lists));
			}
		}
	},
	// 计算属性
	computed: {
		valueCom() {
			// #ifndef VUE3
			return this.value;
			// #endif

			// #ifdef VUE3
			return this.modelValue;
			// #endif
		},
		widthCom(){
			let width = this.width;
			return `${Number(width)}rpx`;
		},
		heightCom() {
			let height = this.height;
			return `${Number(height)}rpx`;
		},
		limitTitleCom() {
			let that = this;
			let { limit } = that;
			let str = "";
			if (limit > 1) {
				let { valueCom: value } = that;
				if (!value) value = [];
				let length = value.length;
				str = `${length} /  ${limit}`;
			}
			return str;
		}
	}
};
</script>

<style lang="scss" scoped>
.vk-data-upload {
	width: 100%;
	text-align: left;
	.chooseImage-view {
		color: #989898;
		background-color: #f8f8fa;
		display: flex;
		justify-content: center;
		align-items: center;
		flex-direction: column;
	}
	.upload-btn {
		border: 1px solid #52a0d5;
		color: #52a0d5;
		background-color: #ffffff;
		border-radius: 8rpx;
		padding: 20rpx 60rpx;
		margin-top: 20rpx;
		line-height: normal;
	}
	.image-mask {
		position: absolute;
		width: 100%;
		height: 100%;
		background-color: rgba(0, 0, 0, 0.4);
		border-radius: 8rpx;
		top: 0;
		left: 0;
		z-index: 2;
		display: flex;
		justify-content: center;
		align-items: center;
	}

	.image-item-view {
		position: relative;
		display: inline-block;
		margin: 10rpx;
		width: 150rpx;
		height: 150rpx;
		.image-item {
			width: 100%;
			height: 100%;
			border-radius: 10rpx;
		}
	}
	.delete-btn {
		position: absolute;
		right: 10rpx;
		top: 10rpx;
		font-size: 30rpx;
		width: 40rpx;
		height: 40rpx;
		border-radius: 50%;
		text-align: center;
		line-height: 36rpx;
		z-index: 3;
		background-color: #565656;
		color: #ffffff;
	}
	.progress {
		font-size: 24rpx;
		width: 70rpx;
		height: 70rpx;
		background-color: #ffffff;
		border-radius: 50%;
		text-align: center;
		line-height: 70rpx;
	}
	.upload-btn-sub {
		width: 150rpx;
		height: 150rpx;
		background-color: #eff8ff;
		border: 1px solid #c3e1ed;
		display: flex;
		align-items: center;
		justify-content: center;
		position: relative;
		.item-1 {
			position: absolute;
			width: 50%;
			border-bottom: 2px solid #489cd3;
		}
		.item-2 {
			position: absolute;
			border-left: 2px solid #489cd3;
			height: 50%;
		}
	}
	.lists-view {
		display: flex;
		flex-direction: row;
		flex-wrap: wrap;
	}
	.default-image {
		width: 128rpx;
		height: 128rpx;
	}
	.header-view {
		padding: 10rpx 20rpx;
		display: flex;
	}
	.left-view {
		width: 70%;
	}
	.right-view {
		width: 30%;
		text-align: right;
	}
}
.vk-data-upload.quick-preview {
	.delete-btn {
		background-color: #ffffff;
		color: #000000;
	}
}
</style>
